package app.goods.info.utils;

import java.awt.Font;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.stream.Collectors;

import org.apache.commons.io.IOUtils;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.util.SheetUtil;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import app.goods.info.constants.GlobalCache;
import app.goods.info.services.domain.GoodsInfo;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import cn.hutool.poi.excel.ExcelUtil;
import cn.hutool.poi.excel.ExcelWriter;

public class FileReaderUtils<T> {
	private static Logger LOGGER = LoggerFactory.getLogger(FileReaderUtils.class);

	public static void main(String[] args) throws IOException {
	}

	/**
	 * 所有的商品单独写一个文件
	 * 
	 * @param goodsInfos
	 * @param excelFileName
	 */
	public static void writeAllGoodsIntoOneExcel(List<GoodsInfo> goodsInfos) {
		// 商品文件根据商品品类分组
//		Map<String, List<GoodsInfo>> catalogueGoods = new HashMap<>();
//		GlobalCache.getInstance().getTargetGoodsNames().forEach(cataGoodsName -> {
//			List<GoodsInfo> goodsList = goodsInfos.stream().filter(goodsInfo -> cataGoodsName.getGoodsNames().stream()
//					.anyMatch(gName -> isGoodsName(goodsInfo, gName))).collect(Collectors.toList());
//			catalogueGoods.put(cataGoodsName.getCatalogueName(), goodsList);
//		});
//		catalogueGoods.entrySet().forEach(entry -> {
//			writeAllGoodsIntoOneExcelPageByCatalogue(entry.getKey(), entry.getValue());
//		});
	}

	private static boolean isGoodsName(GoodsInfo goods, String gName) {
		return gName.equals(goods.getGoodsName() + "（" + goods.getGoodsUnit() + "）")
				|| gName.equals(goods.getGoodsName());
	}

	/*
	 * 所有的商品单独写一个文件
	 * 
	 * @param goodsInfos
	 * 
	 * @param excelFileName
	 */
	public static void writeAllGoodsIntoOneExcelPageByCatalogue(String catalogueName, List<GoodsInfo> goodsInfos) {
		Map<String, List<GoodsInfo>> groupedByShopName = goodsInfos.stream()
				.collect(Collectors.groupingBy(GoodsInfo::getShopName));

		List<Map<String, Object>> rows = new ArrayList<>();
		groupedByShopName.entrySet().stream().forEach(entry -> {
			Map<String, Object> row = createNewMapByTrargetGoodsName(catalogueName);
			row.put("供应商", entry.getKey());
			entry.getValue().forEach(goods -> {
				if ("正大翅中".equals(goods.getGoodsName()) || "正大翅根".equals(goods.getGoodsName())
						|| "益客翅中".equals(goods.getGoodsName()) || "益客翅根".equals(goods.getGoodsName())) {
					row.put(goods.getGoodsName() + "（" + goods.getGoodsUnit() + "）", goods.getGoodsPrice());
				} else {
					row.put(goods.getGoodsName(), goods.getGoodsPrice());
				}
			});
			rows.add(row);
		});
		String filePath = getFilePath("targetFiles" + File.separator + catalogueName + DateUtil.today() + "-"
				+ DateUtil.thisHour(true) + ".xlsx");
		// 通过工具类创建writer
		ExcelWriter writer = ExcelUtil.getWriter(filePath);
		// 一次性写出内容，使用默认样式，强制输出标题
		writer.write(rows, true);
		writer.flush();
		writer.setFreezePane(1, 0);

		final int columnCount = writer.getColumnCount();

		for (int i = 0; i < columnCount; i++) {
			if (i == 0) {
				writer.setColumnWidth(i, 30);
			} else {
				writer.setColumnWidth(i, 15);
			}
		}

		// 关闭writer，释放内存
		writer.close();
	}

	private static Map<String, Object> createNewMapByTrargetGoodsName(String catalogueName) {
		// TODO Auto-generated method stub
		Map<String, Object> newMap = new LinkedHashMap<>();
		newMap.put("供应商", "");
		GlobalCache.getInstance().getTargetGoodsNames().forEach(goodsName -> {
			if (goodsName.getCatalogueName().equals(catalogueName)) {
				goodsName.getGoodsNames().forEach(name -> newMap.put(name, "0"));
			}
		});
		return newMap;
	}

	/**
	 * 每个类别的商品单独写一个文件
	 * 
	 * @param goodsInfos
	 * @param excelFileName
	 */
	public static void writeCatalogueGoodsIntoOneExcel(List<GoodsInfo> goodsInfos, String excelFileName) {
		List<Map<String, Object>> rows = new ArrayList<>();
		goodsInfos.stream().forEach(goods -> {
			Map<String, Object> row = new LinkedHashMap<>();
			row.put("供应商", goods.getShopName());
			row.put("商品名称", goods.getGoodsName());
			row.put("销售单位", goods.getGoodsUnit());
			row.put("规格名称", goods.getSpecName());
			row.put("商户指导价", goods.getGoodsPrice());
			rows.add(row);
		});

		// 通过工具类创建writer
		ExcelWriter writer = ExcelUtil.getWriter("targetFiles" + File.separator + excelFileName + "-" + DateUtil.today()
				+ "-" + DateUtil.thisHour(true) + ".xlsx");
		// 合并单元格后的标题行，使用默认标题样式
		// 一次性写出内容，使用默认样式，强制输出标题
		writer.write(rows, true);
		// 关闭writer，释放内存
		writer.close();
	}

	/**
	 * 将所有类别的商品信息写入一个文件
	 * 
	 * @param goodsInfos
	 * @param sheetName
	 */
	public static void writeAllCatalogueGoodsIntoOneExcel(List<GoodsInfo> goodsInfos, String sheetName) {
		List<Map<String, Object>> rows = new ArrayList<>();
		goodsInfos.stream().forEach(goods -> {
			Map<String, Object> row = new LinkedHashMap<>();
			row.put("供应商", goods.getShopName());
			row.put("商品名称", goods.getGoodsName());
			row.put("销售单位", goods.getGoodsUnit());
			row.put("规格名称", goods.getSpecName());
			row.put("商户指导价", goods.getGoodsPrice());
			rows.add(row);
		});

		// 通过工具类创建writer
		ExcelWriter writer = ExcelUtil.getWriter(
				"targetFiles" + File.separator + "品类商品总表-" + DateUtil.today() + "-" + DateUtil.thisHour(true) + ".xlsx",
				sheetName);
		// 合并单元格后的标题行，使用默认标题样式
		// 一次性写出内容，使用默认样式，强制输出标题
		writer.write(rows, true);
		// 关闭writer，释放内存
		writer.close();
	}

	private static void getSampleDataToExcel() {
		String jsonString = readJsonFileByLines("src/goods.txt");
		JSONObject json = JSONUtil.parseObj(jsonString);
		JSONArray allGoods = json.getJSONObject("result").getJSONArray("goods");
		// 通过工具类创建writer
		ExcelWriter writer = ExcelUtil.getWriter("src/ShopGoods.xlsx");
		List<String> row1 = CollUtil.newArrayList("供应商名称", "商品名称", "商品价格", "单位");

		List<List<String>> rows = new ArrayList<List<String>>();

		for (Object object : allGoods) {
			JSONObject goodJsonObject = (JSONObject) object;
			List<String> row = new ArrayList<String>();
			row.add("宿迁市高粱红食品有限公司");
			row.add(goodJsonObject.getStr("goods_name"));
			row.add(goodJsonObject.getStr("goods_price"));
			row.add(goodJsonObject.getStr("goods_unit"));
			rows.add(row);
		}

		writer.write(rows, true);
		// 关闭writer，释放内存
		writer.close();
	}

	private static void dealWithCatalogues() {
		JSONArray targetArray = new JSONArray();
		String goodsCatalogues = readJsonFileByLines("src/main/resources/goodsCatalogues.txt");
		JSONObject json = JSONUtil.parseObj(goodsCatalogues);
		JSONArray allGoodsCatalogues = json.getJSONObject("result").getJSONArray("catalogues");
		allGoodsCatalogues.forEach(cata -> {
			JSONObject cataJsonObject = (JSONObject) cata;
			JSONObject tagetJsonObject = new JSONObject();
			if (cataJsonObject.getStr("catalogue_name").contains("（集采）")
					&& !cataJsonObject.getStr("catalogue_name").equals("半成品（集采）")) {
				tagetJsonObject = getTargetCatalogue(cataJsonObject);
				targetArray.add(tagetJsonObject);
			}
		});
		writeJsonToFileByLine(JSONUtil.toJsonPrettyStr(targetArray), "src/main/resources/target_goods_catalogues.json");
	}

	private static JSONObject getTargetCatalogue(JSONObject cataJsonObject) {
		JSONObject tagetJsonObject = new JSONObject();
		tagetJsonObject.set("catalogue_name", cataJsonObject.getStr("catalogue_name"));
		tagetJsonObject.set("catalogue_no", cataJsonObject.getStr("catalogue_no"));
		tagetJsonObject.set("children", getTargetChildren(cataJsonObject.getJSONArray("children")));
		return tagetJsonObject;
	}

	private static JSONArray getTargetChildren(JSONArray children) {
		JSONArray targetChildren = new JSONArray();
		if (children.size() > 0) {
			children.forEach(c -> {
				targetChildren.add(((JSONObject) c).getStr("catalogue_no"));
				if (((JSONObject) c).getJSONArray("children") != null) {
					targetChildren.addAll(getTargetChildren(((JSONObject) c).getJSONArray("children")));
				}
			});
		}
		return targetChildren;
	}

	private static void dealWithTargetShops() {
		List<String> targetShops = readFileByLines("src/main/resources/target_shops.txt");
		Properties properties = PropertiesUtils.getAllKeyValue("shopinfo.properties");
		properties.entrySet().forEach(all -> {
			targetShops.forEach(tt -> {
				if (all.getValue().equals(tt)) {
					PropertiesUtils.setValueForKey("target_shop.properties", (String) all.getKey(),
							(String) all.getValue());
				}
			});
		});
	}

	public static void renameFile(String dirPath) {
		File dir = new File(dirPath);
		if (dir.exists() && dir.isDirectory()) {
			File[] files = dir.listFiles();
			if (files != null) {
				for (File subFile : files) {
					if (subFile.exists()) {
						if (subFile.isDirectory()) {
							renameFile(subFile.getAbsolutePath());
						} else {
							System.out.println(subFile.getAbsolutePath());
							String fileName = subFile.getName();
							fileName = fileName.replace("/", "");
//                            fileName=fileName.replace("*","");
							fileName = fileName.replace(":", "-");
							fileName = fileName.replace("、", "-");
							fileName = fileName.replace("：", "");
							fileName = fileName.replace("?", "");
							fileName = fileName.replace("<", "");
							fileName = fileName.replace(">", "");
							fileName = fileName.replace("\"", "");
							fileName = fileName.replace("|", "");
							String newFilePath = subFile.getAbsolutePath().substring(0,
									subFile.getAbsolutePath().lastIndexOf("/")) + "/" + fileName;
							subFile.renameTo(new File(newFilePath));
						}
					}
				}
			}
		}
	}

	/**
	 * 以行为单位读取文件，常用于读面向行的格式化文件
	 */
	public static List<String> readFileByLinesNoRepeat(String fileName) {
		List<String> list = new ArrayList<>();
		File file = new File(fileName);
		BufferedReader reader = null;
		int i = 0;
		try {
			reader = new BufferedReader(new FileReader(file));
			String tempString = null;
			// 一次读入一行，直到读入null为文件结束
			while ((tempString = reader.readLine()) != null) {
				if (!list.contains(tempString)) {
					list.add(tempString);
					i++;
				}
			}
		} catch (IOException e) {
//			LOGGER.error(e.getMessage(), e);
		} finally {
			if (reader != null) {
				try {
					reader.close();
				} catch (IOException e1) {
				}
			}
		}
		return list;
	}

	/**
	 * 以行为单位读取文件，常用于读面向行的格式化文件
	 */
	public static List<String> readFileByLines(String fileName) {
		List<String> list = new ArrayList<>();
		File file = new File(fileName);
		BufferedReader reader = null;
		try {
			reader = new BufferedReader(new FileReader(file));
			String tempString = null;
			// 一次读入一行，直到读入null为文件结束
			while ((tempString = reader.readLine()) != null) {
				list.add(tempString);
			}
			reader.close();
		} catch (IOException e) {
//			LOGGER.error(e.getMessage(), e);
		} finally {
			if (reader != null) {
				try {
					reader.close();
				} catch (IOException e1) {
				}
			}
		}
		return list;
	}

	public static void write(List<String> data) {
		try {

			File file = new File("src/A线下浏览.txt");

			// if file doesnt exists, then create it
			if (!file.exists()) {
				file.createNewFile();
			}

			// true = append file
			FileWriter fileWritter = new FileWriter(file, true);
			BufferedWriter bufferWritter = new BufferedWriter(fileWritter);
			for (String sql : data) {
				bufferWritter.write(sql + "\n");
			}
			bufferWritter.flush();
			bufferWritter.close();
		} catch (IOException e) {
//			LOGGER.error(e.getMessage(), e);
		}
	}

	public static <T> void writeListToFile(List<T> data, String fileName) {
		try {
			String filePath = getFilePath(fileName);

			File file = new File(filePath);

			// if file doesnt exists, then create it
			if (!file.exists()) {
				file.createNewFile();
			}

			// true = append file
			FileWriter fileWritter = new FileWriter(file, false);
			BufferedWriter bufferWritter = new BufferedWriter(fileWritter);
			for (T t : data) {
				bufferWritter.write(t + "\n");
			}
			bufferWritter.flush();
			bufferWritter.close();
		} catch (IOException e) {
//			LOGGER.error(e.getMessage(), e);
		}
	}

	/**
	 * 以行为单位读取文件，常用于读面向行的格式化文件
	 */
	public static List<String> readFileByLines1(String fileName) {
		List<String> list = new ArrayList<>();
		File file = new File(fileName);
		BufferedReader reader = null;
		try {
			reader = new BufferedReader(new FileReader(file));
			String tempString = null;
			// 一次读入一行，直到读入null为文件结束
			while ((tempString = reader.readLine()) != null) {
				list.add(tempString);
			}
			reader.close();
		} catch (

		IOException e) {
//			LOGGER.error(e.getMessage(), e);
		} finally {
			if (reader != null) {
				try {
					reader.close();
				} catch (IOException e1) {
				}
			}
		}
		return list;
	}

	public static List<String> readLineByNioNoRepeat(String fileName) {
		List<String> list = new ArrayList<>();
		RandomAccessFile randomAccessFile = null;
		try {
			randomAccessFile = new RandomAccessFile(fileName, "rw");

			FileChannel channel = randomAccessFile.getChannel();
			ByteBuffer buffer = ByteBuffer.allocate(1024 * 1024);
			int bytesRead = channel.read(buffer);
			ByteBuffer stringBuffer = ByteBuffer.allocate(20);
			int i = 0;
			while (bytesRead != -1) {
				// 之前是写buffer，现在要读buffer
				buffer.flip();// 切换模式，写->读
				while (buffer.hasRemaining()) {
					byte b = buffer.get();
					if (b == 10 || b == 13) { // 换行或回车
						stringBuffer.flip();
						// 这里就是一个行
						final String line = Charset.forName("utf-8").decode(stringBuffer).toString();
						if (!list.contains(line)) {
							list.add(line);
							i++;
						}
						stringBuffer.clear();
					} else {
						if (stringBuffer.hasRemaining()) {
							stringBuffer.put(b);
						} else { // 空间不够扩容
							stringBuffer = reAllocate(stringBuffer);
							stringBuffer.put(b);
						}
					}
				}
				buffer.clear();// 清空,position位置为0，limit=capacity
				// 继续往buffer中写
				bytesRead = channel.read(buffer);
			}
		} catch (FileNotFoundException e) {
//			LOGGER.error(e.getMessage(), e);
		} catch (IOException e) {
//			LOGGER.error(e.getMessage(), e);
		} finally {
			try {
				randomAccessFile.close();
			} catch (IOException e) {
//				LOGGER.error(e.getMessage(), e);
			}
		}
		return list;
	}

	private static ByteBuffer reAllocate(ByteBuffer stringBuffer) {
		final int capacity = stringBuffer.capacity();
		byte[] newBuffer = new byte[capacity * 2];
		System.arraycopy(stringBuffer.array(), 0, newBuffer, 0, capacity);
		return (ByteBuffer) ByteBuffer.wrap(newBuffer).position(capacity);
	}

	public static <T> void writeListToFile(String content, String filePath) {
		try {

			File file = FileUtil.file("targetFiles" + File.separator + filePath);

			// if file doesnt exists, then create it
			if (!file.exists()) {
				file.createNewFile();
			}

			// true = append file
			FileWriter fileWritter = new FileWriter(file, false);
			BufferedWriter bufferWritter = new BufferedWriter(fileWritter);
			bufferWritter.write(content);
			bufferWritter.flush();
			bufferWritter.close();
		} catch (IOException e) {
//			LOGGER.error(e.getMessage(), e);
		}
	}

	public static <T> void writeJsonToFileByLine(String content, String filePath) {
		try {

			File file = new File(getFilePath(filePath));
			LOGGER.info("file=====" + file);
			// if file doesnt exists, then create it
			if (!file.exists()) {
				LOGGER.info("bbefore=====");
				file.createNewFile();
				LOGGER.info("after=====");
			}
			FileUtil.writeString(content, file, StandardCharsets.UTF_8);
			LOGGER.info("content6=====");
		} catch (Exception e) {
			e.printStackTrace();
			LOGGER.info("content6===== " + e.getMessage());
			LOGGER.error(e.getMessage(), e);
		}
	}

	public static <T> void writeToCSVFileByLine(String filePath, String contentLine) {
		try {

			File file = new File(filePath);

			// if file doesnt exists, then create it
			if (!file.exists()) {
				file.createNewFile();
			}

			// true = append file
			FileWriter fileWritter = new FileWriter(file, true);
			BufferedWriter bufferWritter = new BufferedWriter(fileWritter);
			bufferWritter.write(contentLine + "\n");
			bufferWritter.flush();
			bufferWritter.close();
		} catch (IOException e) {
//			LOGGER.error(e.getMessage(), e);
		}
	}

	/**
	 * 以行为单位读取文件，常用于读面向行的格式化文件
	 */
	public static List<String> readFileToStrByLines(String fileName) {
		List<String> yamlList = new ArrayList<>();
		String result = "";
		File file = new File(fileName);
		BufferedReader reader = null;
		try {
			reader = new BufferedReader(new FileReader(file));
			String tempString = null;
			// 一次读入一行，直到读入null为文件结束
			while ((tempString = reader.readLine()) != null) {
				result = result.concat(tempString).concat("\n");
				if ("---".equals(tempString)) {
					yamlList.add(result);
					result = "";
				}
			}
			yamlList.add(result);
			reader.close();
		} catch (IOException e) {
//			LOGGER.error(e.getMessage(), e);
		} finally {
			if (reader != null) {
				try {
					reader.close();
				} catch (IOException e1) {
//					LOGGER.error(e1.getMessage(), e1);
				}
			}
		}
		return yamlList;
	}

	public static String readFileFromResources(String fileName) {
		InputStream inputStream = FileReaderUtils.class.getResourceAsStream(File.separator.concat(fileName));
		String jsonString = null;
		try {
			jsonString = IOUtils.toString(inputStream, "UTF-8");
		} catch (Exception e) {
//			LOGGER.error(e.getMessage(), e);
		}
		return jsonString;
	}

	public static List<String> readLinesFromResources(String fileName) {
		InputStream inputStream = FileReaderUtils.class.getResourceAsStream(File.separator.concat(fileName));
		List<String> lines = null;
		try {
			lines = IOUtils.readLines(inputStream);
		} catch (Exception e) {
//			LOGGER.error(e.getMessage(), e);
		}
		return lines;
	}

	/**
	 * 以行为单位读取文件，常用于读面向行的格式化文件
	 */
	public static String readJsonFileByLines(String fileName) {
		String list = "";
		File file = new File(getFilePath(fileName));
		BufferedReader reader = null;
		try {
			reader = new BufferedReader(new FileReader(file));
			String tempString = null;
			// 一次读入一行，直到读入null为文件结束
			while ((tempString = reader.readLine()) != null) {
				list = list.concat(tempString);
			}
			reader.close();
		} catch (IOException e) {
//			LOGGER.error(e.getMessage(), e);
		} finally {
			if (reader != null) {
				try {
					reader.close();
				} catch (IOException e1) {
//					LOGGER.error(e1.getMessage(), e1);
				}
			}
		}
		return list;
	}

	public static String readFileQuikly(String fileName) {
//		LOGGER.debug("File path: {}", getFilePath(fileName));
		String filePath = getFilePath(fileName);
		String content = FileUtil.readString(new File(filePath), StandardCharsets.UTF_8);
//		LOGGER.debug("File content: {}", content);
		return content;
	}

	public static String getFilePath(String fileName) {
		// 程序当前运行所在目录
		String currentPath = FileUtil.getAbsolutePath(System.getProperty("user.dir"));
		return currentPath.concat(File.separator).concat(fileName);
	}

}